package com.wasu.vod.utils;

import org.apache.commons.net.ftp.FTPClient;
import org.apache.commons.net.ftp.FTPFile;
import org.apache.commons.net.ftp.FTPReply;
import org.apache.log4j.Logger;

import java.io.*;
import java.net.SocketException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;


/**  
 * ftp Client  
 *   
 * @author gyj  
 * @version $Revision: 1.1 $ $Date: 2010/03/26  $  
 */  
  
public class FtpUtil {   
    private String server;   

    private int port;
    
    private String username;   
  
    private String password;   
  
    private FTPClient ftp;   
  
    private boolean binaryTransfer = false;   
  

    public static final List<String> specialCharactors = new ArrayList<String>(Arrays.asList("_","+","-","@",":","\'","\"","™"));
   
    private int soTimeOut;
    /**
     * @param server
     *            ftp服务器地址
     * @param username
     *            ftp服务器登陆用户
     * @param password
     *            ftp用户密码
     */
    public FtpUtil(String server, int port , String username, String password) {
  
        this.server = server;   
        this.port = port;
        this.username = username;   
        this.password = password;  
        ftp = new FTPClient();
        /*  
         * if(Configuration.PrintFTPCommandLog){ //打印FTP命令  
         * ftp.addProtocolCommandListener(new PrintCommandListener()); }  
         */  
    }
    public FtpUtil(String server, int port , String username, String password, int connectTimeOut, int soTimeOut) {
    	  
        this.server = server;   
        this.port = port;
        this.username = username;   
        this.password = password;   
        this.soTimeOut = soTimeOut;
        ftp = new FTPClient();
        ftp.setConnectTimeout(connectTimeOut);
        /*  
         * if(Configuration.PrintFTPCommandLog){ //打印FTP命令  
         * ftp.addProtocolCommandListener(new PrintCommandListener()); }  
         */  
    }
    public FtpUtil()
    {
    	
    }
    public FtpUtil initFtpbyFtpUrl(String ftpurl)
    {
    	ftpurl = ftpurl.substring(ftpurl.indexOf("//") + 2,ftpurl.length());//去掉ftp://字样
		username = ftpurl.substring(0,ftpurl.indexOf(":"));
		ftpurl =  ftpurl.replace(username + ":", "");//去掉username
		password = ftpurl.substring(0,ftpurl.indexOf("@"));
		ftpurl =  ftpurl.replace(password + "@", "");//去掉password
		port=21;
		if(ftpurl.contains(":")){
			server = ftpurl.substring(0,ftpurl.indexOf(":"));
			ftpurl =  ftpurl.replace(server + ":", "");//去掉ip
			if(ftpurl.contains("/")){
				port = Integer.parseInt(ftpurl.substring(0,ftpurl.indexOf("/")));
			}
			else{
				port = Integer.parseInt(ftpurl.substring(0,ftpurl.length()));
				//rootpath默认
			}
		}
		else if(ftpurl.contains("/")){
			server = ftpurl.substring(0,ftpurl.indexOf("/"));
		}
		else {
			//最后一级，port和rootpath默认
			server = ftpurl.substring(0,ftpurl.length());
		}
		FtpUtil ftp = new FtpUtil(server,port,username,password);
		return ftp;
    }

    public String getServer(){ return  server;}

    public String getUsername(){ return username;}

    public String getPassword(){ return  password;}

    public int getPort() { return port;}

    public boolean connect() {   
        try {   
            int reply;   
            ftp.connect(server, port);
            // 连接后检测返回码来校验连接是否成功
            reply = ftp.getReplyCode();   
  
            if(soTimeOut > 0){
           	 try {
        			ftp.setSoTimeout(soTimeOut);
        		} catch (SocketException e) {
        			e.printStackTrace();
        		}
           }
            if (FTPReply.isPositiveCompletion(reply)) {
                if (ftp.login(username, password)) {   
                    // 设置为passive模式   
                    ftp.enterLocalPassiveMode();   
                    return true;
                }   
            } else {   
                ftp.disconnect();
                System.out.println("FTP server refused connection.");   
            }
        } catch (IOException e) {   
            if (ftp.isConnected()) {   
                try {   
                    ftp.disconnect();   
                } catch (IOException f) {   
                }   
            }   
            System.out.println("Could not connect to server.");   
        }   
        return false;   
    }   
  
    /**  
     * 下载一个文件到默认的本地路径中  
     *   
     *            文件名称(不含路径)
     * @param delFile  
     *            成功后是否删除该文件  
     * @return  
     */  
    public boolean get(String remoteFileName,String localFileName,boolean delFile) { 
//    	String remote = PropertyManager.getProperty("RemotePutPath") + fileName;   
//      String local = PropertyManager.getProperty("LocalPutPath")+ fileName;  
        return getFile(remoteFileName, localFileName, delFile);   
    }   
  
    /**  
     * 上传一个文件到默认的远程路径中  
     *   
     *            文件名称(不含路径)
     * @param delFile  
     *            成功后是否删除该文件  
     * @return  
     */  
    public boolean put(String remoteFileName,String localFileName, boolean delFile) {   
//        String remote = PropertyManager.getProperty("RemotePutPath") + fileName;   
//        String local = PropertyManager.getProperty("LocalPutPath")+ fileName;   
          return putFile(remoteFileName, localFileName, delFile);   
    }   
    
    public boolean put(String fileName,boolean delFile) {   
      String remote = PropertyManager.getProperty("RemotePutPath") + fileName;   
      String local = PropertyManager.getProperty("LocalPutPath")+ fileName;   
      return putFile(remote, local, delFile);   
    }  
  
    /**  
     * 上传多个文件到默认的远程路径中  
     *   
     * @param fileNames  
     *            文件名数组  
     * @param delFile  
     *            成功后是否删除文件  
     * @return  
     */  
    public boolean[] put(String[] fileNames, boolean delFile) {   
        boolean[] result = new boolean[fileNames.length];   
        for (int j = 0; j < result.length; j++) {   
            result[j] = false;   
        }   
        String remoteFile;   
        String localFile;
        for (int i = 0; i < fileNames.length; i++) {
            localFile = fileNames[i];   
            result[i] = put(localFile, delFile);   
        }   
        return result;   
    }   
  
    /**  
     * 上传一个文件到远程指定文件  
     *   
     * @param remoteAbsoluteFile  
     *            远程文件名(包括完整路径)  
     * @param content  
     *            文件内容
     * @param encode  
     *            文件编码      
     */ 
    public boolean putContent(String remoteAbsoluteFile, String content, String encode) {     	
    	System.out.println("=====>远程文件:"+remoteAbsoluteFile);
    	remoteAbsoluteFile = remoteAbsoluteFile.replace("\\", "/");
        String remoteDirectory=remoteAbsoluteFile.substring(0,remoteAbsoluteFile.lastIndexOf("/")); //远程目录
        String remoteFileName = remoteAbsoluteFile.substring(remoteAbsoluteFile.lastIndexOf("/")+1,remoteAbsoluteFile.length()); //远程文件名
        InputStream input = null;
        try {
        	//设置文件传输类型  
        	 if (binaryTransfer) {   
                 ftp.setFileType(FTPClient.BINARY_FILE_TYPE);   
             } else {   
                 ftp.setFileType(FTPClient.ASCII_FILE_TYPE);   
             }
        	 if(!ftp.changeWorkingDirectory(remoteDirectory)){//目录不存在
        		 String[] dirArr = remoteDirectory.split("/");
        		 if(dirArr != null ) {
        			 for(String dir:dirArr){
        				 if(dir != null && !"".equals(dir) && !ftp.changeWorkingDirectory(dir)){
        					 if(!ftp.makeDirectory(dir)){
            					 System.out.println("=====>创建文件夹失败:"+dir + "||" + remoteDirectory);
                    			 return false;
            				 }
        					 else {
        						 ftp.changeWorkingDirectory(dir);
        					 }
        				 } 
        			 }
        		 }
             }
        	 //ftp.changeWorkingDirectory(remoteDirectory);

        	// 处理传输   
            input = new ByteArrayInputStream(content.getBytes(encode)); 
            ftp.storeFile(remoteFileName, input); 
    		System.out.println("put 文件内容" + content);  
    		return true;
    	} catch (Exception e) {
    		e.printStackTrace();
    		return false;
    	} finally {   
            try {   
                if (input != null) {   
                    input.close();   
                } 
                this.disconnect();
            } catch (Exception e2) {  
            	e2.printStackTrace();
            }   
        }  
    }
    /**  
     * 上传一个本地文件到远程指定文件  
     *   
     * @param remoteAbsoluteFile  
     *            远程文件名(包括完整路径)  
     * @param localAbsoluteFile  
     *            本地文件名(包括完整路径)  
     * @return 成功时，返回true，失败返回false  
     */  
    private boolean putFile(String remoteAbsoluteFile, String localAbsoluteFile,   
            boolean delFile) {   
        InputStream input = null;
        System.out.println("=====>远程文件:"+remoteAbsoluteFile+",本地文件:"+localAbsoluteFile);
        try {   
            // //设置文件传输类型   
            if (binaryTransfer) {   
                ftp.setFileType(FTPClient.BINARY_FILE_TYPE);   
            } else {   
                ftp.setFileType(FTPClient.ASCII_FILE_TYPE);   
            }   
            //判断远程目录是否存在
            remoteAbsoluteFile = remoteAbsoluteFile.replace("\\", "/");
            String remoteDirectory=remoteAbsoluteFile.substring(0,remoteAbsoluteFile.lastIndexOf("/")+1); //远程目录
            if(!ftp.changeWorkingDirectory(remoteDirectory)){//目录不存在
              System.out.println("====>远程目录:"+remoteDirectory+"不存在");
              return false;
            }
            // 处理传输   
            input = new FileInputStream(localAbsoluteFile);   
            ftp.storeFile(remoteAbsoluteFile, input);   
            System.out.println("put " + localAbsoluteFile);   
            input.close();   
            if (delFile) {   
                (new File(localAbsoluteFile)).delete(); //删除本地文件 
                System.out.println("delete " + localAbsoluteFile); 
            }  
           return true;   
        } catch (FileNotFoundException e) {        	
            System.out.println("local file not found.");
        } catch (IOException e1) {   
            System.out.println("Could put file to server.");
        } finally {   
            try {   
                if (input != null) {   
                    input.close();   
                }   
            } catch (Exception e2) {  
              System.out.println("cause exception.");
            }   
        }   
  
        return false;   
    }   
  
    /**  
     * 下载一个远程文件到本地的指定文件  
     *   
     * @param remoteAbsoluteFile  
     *            远程文件名(包括完整路径)  
     * @param localAbsoluteFile  
     *            本地文件名(包括完整路径)  
     * @return 成功时，返回true，失败返回false  
     */  
    public boolean getFile(String remoteAbsoluteFile, String localAbsoluteFile,   
            boolean delFile) {   
        OutputStream output = null;   
        try {   
            // 设置文件传输类型   
            if (binaryTransfer) {   
                ftp.setFileType(FTPClient.BINARY_FILE_TYPE);   
            } else {   
                ftp.setFileType(FTPClient.ASCII_FILE_TYPE);   
            }
            //判断远程目录是否存在
            remoteAbsoluteFile = remoteAbsoluteFile.replace("\\", "/");
            String remoteDirectory=remoteAbsoluteFile.substring(0,remoteAbsoluteFile.lastIndexOf("/")+1); //远程目录
            if(!ftp.changeWorkingDirectory(remoteDirectory)){//目录不存在
              System.out.println("====>远程目录:"+remoteDirectory+"不存在");
              return false;
            }
            // 处理传输   
            output = new FileOutputStream(localAbsoluteFile);   
            ftp.retrieveFile(remoteAbsoluteFile, output);   
            output.close();   
            if (delFile) { // 删除远程文件   
                ftp.deleteFile(remoteAbsoluteFile);   
            }   
            return true;   
        } catch (FileNotFoundException e) {   
            System.out.println("local file not found.");   
        } catch (IOException e1) {   
            System.out.println("Could get file from server.");   
        } finally {   
            try {   
                if (output != null) {   
                    output.close();   
                }   
            } catch (IOException e2) {   
            }   
        }   
        return false;   
    }   
  
    /**  
     * 列出远程目录下所有的文件  
     *   
     * @param remotePath  
     *            远程目录名  
     * @return 远程目录下所有文件名的列表，目录不存在或者目录下没有文件时返回0长度的数组  
     */  
    public String[] listNames(String remotePath) {   
        String[] fileNames = null;   
        try {   
            FTPFile[] remotefiles = ftp.listFiles(remotePath);
            fileNames = new String[remotefiles.length];   
            for (int i = 0; i < remotefiles.length; i++) {   
                fileNames[i] = remotefiles[i].getName();   
            }   
  
        } catch (IOException e) {   
            System.out.println("Could not list file from server.");   
        }   
        return fileNames;   
    }   
  
    /**  
     * 断开ftp连接  
     */  
    public void disconnect() {   
        try {   
            ftp.logout();   
            if (ftp.isConnected()) {   
                ftp.disconnect();   
            }   
        } catch (IOException e) {   
            System.out.println("Could not disconnect from server.");   
        }   
    }   
  
    /**  
     * @return Returns the binaryTransfer.  
     */  
    public boolean isBinaryTransfer() {   
        return binaryTransfer;   
    }   
  
    /**  
     * @param binaryTransfer  
     *            The binaryTransfer to set.  
     */  
    public void setBinaryTransfer(boolean binaryTransfer) {   
        this.binaryTransfer = binaryTransfer;   
    }


    public static String removeSpecialCharactor(String ftpUrl){

        for ( String specialCharactor : specialCharactors){
             ftpUrl = ftpUrl.replace(specialCharactor,"");
        }
        return ftpUrl;

    }
    //ftpUrl格式icms_icds_pub02/opnewsps02/Video/2017/02/10/09/F28146B5039F457BA69FEDA8225E6977_1535032474.ts
    //将文件移动到去掉特殊字符的路径下
    public boolean moveFile(String ftpUrl) {
        //去掉特殊字符
        String removeSpecialCharactorFtpUrl = removeSpecialCharactor(ftpUrl);
        String directory=removeSpecialCharactorFtpUrl.substring(0,removeSpecialCharactorFtpUrl.lastIndexOf("/")); //目录
        String fileName = removeSpecialCharactorFtpUrl.substring(removeSpecialCharactorFtpUrl.lastIndexOf("/")+1); //
        String[] dirArr = directory.split("/");
        try {
            if (dirArr != null) {
                for (String dir : dirArr) {
                    if (dir != null && !"".equals(dir) && !ftp.changeWorkingDirectory(dir)) {
                        if (!ftp.makeDirectory(dir)) {
                            System.out.println("=====>创建文件夹失败:" + dir + "||" + directory);
                            return false;
                        } else {
                            ftp.changeWorkingDirectory(dir);
                        }
                    }
                }
            }
            //判断文件是否存在,文件存在不需要移动
            FTPFile[] files = ftp.listFiles();
            for (FTPFile file : files) {
                if (file.getName().equals(fileName)) {
                    System.out.println("文件存在，文件路径:" + removeSpecialCharactorFtpUrl);
                    return true;
                }
            }
            System.out.println("ftp rename :ftpUrl="+ftpUrl+" removeSpecialCharactorFtpUrl="+removeSpecialCharactorFtpUrl);
            return ftp.rename("/" + ftpUrl, "/" + removeSpecialCharactorFtpUrl);
        }catch (Exception e){
            e.printStackTrace();
            System.out.println("移动文件异常，ftpUrl:" + ftpUrl + ",removeSpecialCharactorFtpUrl:" + removeSpecialCharactorFtpUrl);
            return false;
        }finally {
            this.disconnect();
        }
    }
    
    //old格式/wasu/icms_icds_pub02/opnewsps02/Video/2017/02/10/09/F28146B5039F457BA69FEDA8225E6977_1535032474.ts
    //new格式/wasu/20170725/F28146B5039F457BA69FEDA8225E6977_1535032474.ts
    //将文件移动到指定的路径下
    public boolean moveFile(String oldPath,String newPath) {  
        String directory = newPath.substring(0,newPath.lastIndexOf("/")); //目录
        String fileName = newPath.substring(newPath.lastIndexOf("/")+1); //
        String[] dirArr = directory.split("/");
        try {
            if (dirArr != null) {
                for (String dir : dirArr) {
                    if (dir != null && !"".equals(dir) && !ftp.changeWorkingDirectory(dir)) {
                        if (!ftp.makeDirectory(dir)) {
                        	System.out.println("=====>创建文件夹失败:" + dir + "||" + directory);
                            return false;
                        } else {
                            ftp.changeWorkingDirectory(dir);
                        }
                    }
                }
            }
            //判断文件是否存在,文件存在不需要移动
            FTPFile[] files = ftp.listFiles();
            for (FTPFile file : files) {
                if (file.getName().equals(fileName)) {
                	System.out.println("文件存在，文件路径:" + newPath);
                    return true;
                }
            }
            System.out.println("ftp rename :文件的初始路径："+oldPath+" 指定的文件路径："+newPath);
            boolean isRename = ftp.rename(oldPath, newPath);
            if(!isRename){
            	System.out.println("文件移动失败,设置重试机制");
            	 boolean isTry = true ;
            	 long begin = System.currentTimeMillis();
            	while(isTry){
            		Thread.sleep(2000);
            		long cuurent = System.currentTimeMillis();
            		  boolean sesscu = ftp.rename(oldPath, newPath);
            		 if(sesscu||(cuurent-begin)>5*60*1000){
            			 isTry =false ;
            		 }
            		 isRename = sesscu ;
            	}
            	
            }else{
            	return isRename ;
            }
            
            return isRename;            
        }catch (Exception e){
            e.printStackTrace();
            System.out.println("移动文件异常，文件的初始路径:" + oldPath + ",指定的文件路径:" + newPath+"异常："+e);
            return false;
        }finally {
           try {
			ftp.disconnect();
		} catch (IOException e) {
			e.printStackTrace();
			
		}
        }
    }

    public static void main(String[] args) {   
    	String fileContent = "hello";
    	FtpUtil fileUtil = new FtpUtil("125.210.163.73",21,"itvdev","dev@2018itv", 3000, 3000);
    	fileUtil.connect();
    	fileUtil.putContent("/testftp.xml",fileContent, "utf-8");
       
    }   
}  


